﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data.SqlClient;
using System.Globalization;
using System.Reflection;
using System.Web;
using EPiCloner.EventHandlers;
using EPiServer;
using EPiServer.Core;
using EPiServer.DataAbstraction;
using EPiServer.DataAccess;
using EPiServer.SpecializedProperties;
using EPiServer.Web;

namespace EPiCloner
{
    public partial class Cloner
    {
        public event EventHandler PreCloning;
        public event PageCloningEventHandler Cloning;
        public event EventHandler PostCloning;
        public event EventHandler Cloned;
        public event GetChildrenEventHandler GetChildren;
        
        private LanguageBranch _sourceLanguage;
        
        private string _rootPageName = string.Empty;
        private bool _publish;
        private bool _suppressExceptions;
        
        private bool _updatePageReferences;
        
        private PageReference _firstClonedPage;
        private bool _isHeadCreated;
        private string _statusMessage = "Cloning finished at {0}. {1} Pages has been created";

        private Dictionary<PageReference, PageReference> PageRefMappings = new Dictionary<PageReference, PageReference>();

        private Cloner()
        {
            Cloning += PageCloning;
        }

        public static string Clone(PageReference sourceReference, PageReference targetParent, LanguageBranch targetLanguage, Action<Cloner> actions)
        {
            //Initialize Cloner
            var cloner = new Cloner();
            string message;
            var sourceData = DataFactory.Instance.GetPage(sourceReference);
            cloner._sourceLanguage = new LanguageBranch(new CultureInfo(sourceData.LanguageBranch));

            // Cascade cloner object initialization
            actions(cloner);

            try
            {
                cloner.OnPreCloning(new EventArgs());
                var pageCount = cloner.OnCloning(new PageCloningEventArgs(sourceReference, targetParent, cloner._sourceLanguage, targetLanguage, cloner._rootPageName));
                cloner.OnPostCloning(new EventArgs());
                
                cloner.OnCloned(new EventArgs());

                message = string.Format(cloner._statusMessage, DateTime.Now.ToLongTimeString(), pageCount);
            }
            catch(SqlException ex)
            {
                message = "Try <a href='/EPiSiteVerification.aspx'>Site Structure Validation</a> First<br/>" +
                          ex.ToString();
            }
            catch (Exception ex)
            {
                message = ex.ToString();
            }

            return message;
        }

        protected virtual void OnPreCloning(EventArgs e)
        {
            EventHandler handler = PreCloning;
            if (handler != null) handler(this, e);
        }


        protected virtual int OnCloning(PageCloningEventArgs e)
        {
            PageCloningEventHandler handler = Cloning;
            if (handler != null)
            {
                return handler(e);
            }
            return 0;
        }

        protected virtual void OnPostCloning(EventArgs e)
        {
            EventHandler handler = PostCloning;
            if (handler != null) handler(this, e);
        }

        public void OnCloned(EventArgs e)
        {
            EventHandler handler = Cloned;
            if (handler != null) handler(this, e);
        }

        public PageDataCollection OnGetChildren(GetChildrenEventArgs e)
        {
            GetChildrenEventHandler handler = GetChildren;
            if (handler != null)
                return handler(e);
            return null;
        }

        #region Cascade Init

        public Cloner SetPageName(string pageName)
        {
            _rootPageName = pageName;
            return this;
        }
        
        public Cloner ShouldPublish(bool publish)
        {
            _publish = publish;
            return this;
        }

        public Cloner ShouldCloneDescendents(bool cloneDescendents)
        {
            if (cloneDescendents)
            {
                GetChildren += GetChildrenPages;
            }
            return this;
        }

        public Cloner ShouldUpdatePageReferences(bool updatePageReferences)
        {
            _updatePageReferences = updatePageReferences;
            PostCloning += Cloner_PostCloning;
            return this;
        }

        public Cloner ShouldSuppressExceptions(bool suppressExceptions)
        {
            _suppressExceptions = suppressExceptions;
            return this;
        }

        public Cloner ShouldDisablePageEvents(bool disablePageEvents)
        {
            PreCloning += DisablePageEvents;
            Cloned += EnablePageEvents;
            return this;
        }

        #endregion
    }
}
